#pragma once

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#define PATHNAME "."
#define PROJ_ID 0x66
#define SHM_SIZE 1024
#define FIFO_NA "./readable"

#define ERR_EIXT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0);

struct Shm
{
public:
    Shm(size_t size, int flGet, int flgAt) : _flGet(flGet), _flgAt(flgAt), _size(size) {}
    ~Shm() {};

    void *commShm()
    {
        key_t k = ftok(PATHNAME, PROJ_ID);
        if (k < 0)
            ERR_EIXT("ftok");

        _id = shmget(k, _size, _flGet);
        if (_id < 0)
            ERR_EIXT("shmget");

        _addr = shmat(_id, nullptr, _flgAt);
        if (_addr == (void *)-1)
            ERR_EIXT("shmat");

        return _addr;
    }

    void destoryShm()
    {
        if (shmdt(_addr) < 0)
            ERR_EIXT("shmdt");

        shmctl(_id, IPC_RMID, nullptr);
    }

private:
    int _flGet;
    int _flgAt;
    size_t _size;
    int _id;
    void *_addr;
};

// 复习FIFO，便用命名管道作为信号传输
struct FIFOSig
{
public:
    FIFOSig(const char *mode)
    {
        if (mkfifo(FIFO_NA, 0666) < 0 && errno != EEXIST)
            ERR_EIXT("mkfifo");

        _fp = fopen(FIFO_NA, mode);
        if (!_fp)
            ERR_EIXT("fopen");
    };
    ~FIFOSig(){
        unlink(FIFO_NA);
    };

    int fifoClose(){
        return fclose(_fp);
    }

    void sig()
    {
        int ws = 1;
        if(!fwrite(&ws, sizeof(int), 1, _fp))
            ERR_EIXT("fwrite");
        fflush(_fp);//fwrite要有fflush
    }

    void wait()
    {
        int rs = 0;
        if (!fread(&rs, sizeof(int), 1, _fp))
            ERR_EIXT("fread");
    }

private:
    FILE *_fp;
};